﻿namespace PicCompact
{
    using System;
    using System.Drawing;
    using System.Drawing.Imaging;
    using System.IO;
    using Util;

    class PicCompactMain
    {
        static ImageCodecInfo imgCodecInfo;
        static double sizeRate;
        static int qualityRate;

        /// <summary>
        /// Usage:
        ///  $ bin/Release/PicCompact E:\\input E:\\output 1.0 80 d
        /// or
        ///  $ bin/Release/PicCompact E:\\input E:\\output 1.0 80 s 1024
        /// where the last number means KB.
        /// </summary>
        /// <param name="args"></param>
        static void Main(string[] args)
        {
            DirectoryInfo src = new DirectoryInfo(args[0]);
            DirectoryInfo dst = new DirectoryInfo(args[1]);
            sizeRate = double.Parse(args[2]);
            qualityRate = int.Parse(args[3]);

            imgCodecInfo = ImageProcessor.GetCodecInfo("image/jpeg");

            switch (args[4][0])
            {
                case 'd':
                    FileManager.ForEachFileDirToDirTransfer(src, dst, CompactToDstTransferHandler);
                    break;
                case 's':
                    FileManager.ForEachFileDirToDirTransfer(src, dst, CompactLocallyTransferHandler, int.Parse(args[5]) * 1024);
                    break;
            }
        }

        private static void CompactToDstTransferHandler(FileInfo f, DirectoryInfo dst, params object[] args)
        {
            string dstPic = Path.Combine(dst.FullName, f.Name);
            CompressPicture(f.FullName, dstPic, sizeRate, qualityRate, imgCodecInfo);
        }

        private static void CompactLocallyTransferHandler(FileInfo f, DirectoryInfo dst, params object[] args)
        {
            long sizeThreshold = long.Parse(args[0].ToString());
            if (f.Length >= sizeThreshold)
            {
                string srcPic = f.FullName;
                string dstPic = Path.Combine(dst.FullName, f.Name);
                string tmpPic = Path.Combine(dst.FullName, Guid.NewGuid().ToString("D") + f.Name);

                if (CompressPicture(srcPic, tmpPic, sizeRate, qualityRate, imgCodecInfo))
                {
                    f.MoveTo(dstPic);
                    (new FileInfo(tmpPic)).MoveTo(srcPic);
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sourcePath"></param>
        /// <param name="targetPath"></param>
        /// <param name="sizeRate">0.0 to 1.0</param>
        /// <param name="qualityRate">1 to 100</param>
        /// <param name="info"></param>
        /// <returns></returns>
        private static bool CompressPicture(string sourcePath, string targetPath, double sizeRate, int qualityRate, ImageCodecInfo info)
        {
            try
            {
                Image sourceImage = Image.FromFile(sourcePath);
                Bitmap bmp = new Bitmap(sourceImage, new Size((int)(sourceImage.Width * sizeRate), (int)(sourceImage.Height * sizeRate)));

                foreach (PropertyItem i in sourceImage.PropertyItems)
                {
                    bmp.SetPropertyItem(i);
                }

                EncoderParameter p;
                EncoderParameters ps;
                ps = new EncoderParameters(1);
                p = new EncoderParameter(Encoder.Quality, qualityRate);
                ps.Param[0] = p;
                bmp.Save(targetPath, info, ps);
                bmp.Dispose();

                sourceImage.Dispose();
                GC.Collect();
                return true;
            }
            catch
            {
                return false;
            }
        }
    }
}